<?php
defined('_XR_EXEC') or die();
/* SMTP邮件发送类 */
class emailsmtp
{
	public $priority		= 3; //发送邮件的优称等级(1 = High, 3 = Normal, 5 = low). Default value is 3.
	public $charset			= "iso-8859-1";//字符集 gb2312 utf-8
	public $content_type	= "plain";//邮件是以HTML还是text
	public $encoding		= "base64";//邮件编码 "7bit", "binary", "base64", and "quoted-printable"
	
	public $from			= "#@[]";//发送邮件地址
	public $fromname		= "service";//发送邮件人姓名

	public $subject			= "";//邮件主题
	public $body			= "";//邮件内容

	public $debug			= false;//是否开启调试
	public $timezone		= "+0000";//设置时区

	public $request_notify	= false;//是否有请求通报
	public $temp_folder		= "./";//操作的临时文件夹
	public $error_msg		= "";//出错信息

	// SMTP
	public $host        	= "localhost";//邮件服务器地址IP
	public $port        	= 25;//邮件服务器端口
	public $helo        	= "";//发送测试helo请求
	public $timeout     	= 10; //设置超时长度

	public $to             = array();//收件人地址
	public $cc             = array();//抄送人地址
	public $bcc            = array();//密送人地址
	public $reply_to       = array();//回复人地址
	
	private $version        = "1.0";
	private $attachment     = array();//发送附件
	private $embed_file     = array();
	private $boundary		= false;
	
	private $auth_login 	= false;//是否以登录形式发送
	private $auth_user      = "";//登录用户名
	private $auth_pass      = "";//登录密码
	
	private $smime_sign		= false;//是否签名
	private $smime_crypt	= false;//是否加密
	
	public function __construct($host = "", $port = 25, $user = "", $pass = "", $charset = "utf-8") 
	{
		$this->version = "1.0";
		$this->helo = "helloMail";
		if ($host && $port){self::set_host($host, $port);}//连接邮件服务器地址与端口
		if ($user && $pass){self::user_login($user, $pass);}
		if ($charset){$this->charset = $charset;}
	}
	public function ready($host , $port , $user , $pass , $charset ){
		self::set_host($host, $port);
		self::user_login($user, $pass);
		$this->charset = $charset;
	}

	/**
	 * 析构函数
	 *
	 */
	public function __destruct()
	{
		self::clear();
	}

	/**
	 * 用户登录
	 *
	 * @param string $user username
	 * @param string $pass password
	 */
	public function user_login($user, $pass)
	{
		$this->auth_login 	= true;
		$this->auth_user 	= $user;
		$this->auth_pass 	= $pass;
	}
	
	/**
	 * 是否以HTML发送
	 *
	 * @param boolean $bool
	 */
	public function is_html($bool = true)
	{
		$this->content_type = ($bool) ? "html" : "plain";
	}

	/**
	 * 设置邮件服务器
	 *
	 * @param string $host 主机
	 * @param integer $port 端口号
	 */
	public function set_host($host, $port = 25)
	{
		$this->host = trim($host);
		if (!empty($port)){$this->port = $port;}
	}
	
	/**
	 * 设置邮件发送者信息
	 *
	 * @param string $address email地址
	 * @param string $name email作者名
	 */
	public function set_from($address, $name = "webmaster")
	{
		$this->from = trim($address);
		$this->fromname = $name;
	}

	/**
	 * 增加收件人邮箱与收件人姓名
	 *
	 * @param string $address email地址
	 * @param string $name email作者名
	 */
	public function add_to($address, $name = "")
	{
		$cur = count($this->to);
		$this->to[$cur][0] = trim($address);
		$this->to[$cur][1] = $name;
	}

	/**
	 * 增加抄送人邮箱与抄送人姓名
	 *
	 * @param string $address email地址
	 * @param string $name email作者名
	 */
	public function add_cc($address, $name = "")
	{
		$cur = count($this->cc);
		$this->cc[$cur][0] = trim($address);
		$this->cc[$cur][1] = $name;
	}

	/**
	 * 增加密送人邮箱地址与密送人姓名
	 *
	 * @param string $address email地址
	 * @param string $name email作者名
	 */
	public function add_bcc($address, $name = "")
	{
		$cur = count($this->bcc);
		$this->bcc[$cur][0] = trim($address);
		$this->bcc[$cur][1] = $name;
	}

	/**
	 * 增加回复人邮箱地址与回复人姓名
	 *
	 * @param string $address email地址
	 * @param string $name email作者名
	 */
	public function add_reply_to($address, $name = "")
	{
		$cur = count($this->reply_to);
		$this->reply_to[$cur][0] = trim($address);
		$this->reply_to[$cur][1] = $name;
	}

	/**
	 * 发送邮件
	 *
	 * @return boolean 成功为true失败为flase
	 */
	public function send()
	{
		if (count($this->to) + count($this->cc) + count($this->bcc) == 0)
		{
			$this->error_msg = "You must provide at least one recipient address";
			return false;
		}
		$msgdata = $this->create_msg();
		if (self::_send_mail($msgdata) === false){return false;}
		return $msgdata;//返回邮件格式内容
	}

	/**
	 * 创建邮件信息
	 *
	 * @return string 邮件内容
	 */
	public function create_msg()
	{
		$bConvert = false;
		
		if ($this->smime_sign || $this->smime_crypt)
		{
			$msgdata = self::_create_header(true);
			$msgdata .= self::_create_body();

			$fileid = md5(uniqid(""));
			$newmsgfile = $this->temp_folder."_attachments\\".$this->auth_user.'_'.$fileid."_newmsg.eml";
			$signfile = $this->temp_folder."_attachments\\".$this->auth_user.'_'.$fileid."_signmsg.eml";
			$cryptfile = $this->temp_folder."_attachments\\".$this->auth_user.'_'.$fileid."_cryptmsg.eml";

			if (save_file($newmsgfile, $msgdata))
			{
				$headerInfo = self::_get_header_info(true);

				if ($this->smime_sign)
				{
					$bRet = read_my_acitve_cert($cert, $key);
					if ($bRet && openssl_pkcs7_sign($newmsgfile, $signfile, $cert, $key, $headerInfo))
					{
						$newmsgfile = $signfile;
						$bConvert = true;
					}
				}
				
				if ($this->smime_crypt)
				{
					$arrAddress[] = $this->from;
					for ($i = 0; $i < count($this->to); $i++)
					{
						if (!in_array($this->to[$i][0], $arrAddress))
							$arrAddress[] = $this->to[$i][0];
					}
					for ($i = 0; $i < count($this->cc); $i++)
					{
						if (!in_array($this->to[$i][0], $arrAddress))
							$arrAddress[] = $this->cc[$i][0];
					}
					for ($i = 0; $i < count($this->bcc); $i++)
					{
						if (!in_array($this->to[$i][0], $arrAddress))
							$arrAddress[] = $this->bcc[$i][0];
					}

					$bRet = read_all_receiver_cert($arrAddress, $arrCert);
					if ($bRet && openssl_pkcs7_encrypt($newmsgfile, $cryptfile, $arrCert, $headerInfo))
					{
						$newmsgfile = $cryptfile;
						$bConvert = true;
					}
				}
				
				if ($bConvert)
				{
					$msgdata = read_file($newmsgfile);
					$msgdata = str_replace("\r\n", "\n", $msgdata);
					$msgdata = str_replace("\n", "\r\n", $msgdata);
				}
			}
			@unlink($newmsgfile);
			@unlink($signfile);
			@unlink($cryptfile);
		}
		
		if (!$bConvert)
		{
			$msgdata = self::_create_header();
			$msgdata .= self::_create_body();
		}				
		return $msgdata;
	}

	/**
	 * 增加附件
	 *
	 * @param string $path 路径
	 * @param string $name 文件名
	 * @param string $type 文件类型
	 * @return boolean
	 */
	public function add_attachment($path, $name = "", $type= "application/octet-stream")
	{
		if (!@is_file($path))
		{
			$this->error_msg = sprintf("Could not find %s", $path);
			return false;
		}
		
		$filename = basename($path);
		if ($name == ""){$name = $filename;}
		
		$cur = count($this->attachment);
		$this->attachment[$cur][0] = $path;
		$this->attachment[$cur][1] = $filename;
		$this->attachment[$cur][2] = $name;
		$this->attachment[$cur][3] = $type;
		return true;
	}

	/**
	 * 将附件插入邮件中
	 *
	 * @param string $path 路径
	 * @param string $name 文件名
	 * @param string $filename 文件名
	 * @param string $type 文件类型
	 * @return unknown
	 */
	public function add_embed_file($path, $name, $filename, $type= "image/gif")
	{
		if (!@is_file($path))
		{
			$this->error_msg = sprintf("Could not find %s", $path);
			return false;
		}
		$name = basename($name);
		$cur = count($this->embed_file);
		$this->embed_file[$cur][0] = $path;
		$this->embed_file[$cur][1] = $filename;
		$this->embed_file[$cur][2] = $name;
		$this->embed_file[$cur][3] = $type;
		$this->embed_file[$cur][4] = md5(uniqid(time()));
		return true;
	}

	/**
	 * 以为安全发送邮件
	 *
	 * @param string $sign
	 * @param string $crypt
	 */
	public function use_secure_mime($sign, $crypt)
	{
		$this->smime_sign = $sign;
		$this->smime_crypt = $crypt;
	}

	/**
	 * 清除邮件信息
	 *
	 */
	public function clear()
	{
	   $this->fromname = "";
	   $this->from = "";
	   $this->to = array();
	   $this->cc = array();
	   $this->bcc = array();
	   $this->subject = "";
	   $this->body = "";
	   $this->attachment = array();
	   $this->embed_file = array();
	}
	
	/**
	 * 编码
	 *
	 * @param string $string
	 * @return string
	 */
	private function _mime_encode($string)
	{
		if ($string == ""){return;}
		if (!eregi("^([[:print:]]*)$",$string))
		{
			$string = "=?".$this->charset."?B?".base64_encode($string)."?=";
		}
		return $string;
	}
	
	/**
	 * 设置邮件边界
	 *
	 * @return string
	 */
	private function _get_boundary()
	{
		static $index = 0;
		$boundary = "__b_".sprintf("%03d", $index++)."_".md5(uniqid(time()));
		return $boundary;
	}
	
	/**
	 * 加密文件
	 *
	 * @param string $path 文件路径
	 * @return string
	 */
	private function _encode_file($path)
	{
		$content = read_file($path);
		if ($content === false)
		{
			$this->error_msg = sprintf("Could not find %s", $path);
			return "";
		}
		$encoded = chunk_split(base64_encode($content));
		unset($content);
		return trim($encoded);
	}

	/**
	 * 调整内置文件路径
	 *
	 * @param string $body
	 * @return string
	 */
	private function _adjust_embed_path($body)
	{
		$iEmbedCount = count($this->embed_file); 
		for ($i = 0; $i < $iEmbedCount; $i++)
		{
			$filename = $this->embed_file[$i][1];
			$cid = $this->embed_file[$i][4];
			//$body = eregi_replace("=[\"]?".$filename."+[\"]?", "=\"cid:".$cid."\"", $body);
			$body = str_replace($filename, "cid:".$cid, $body);
		}
		return $body;
	}

	/**
	 * 创建地址
	 *
	 * @param string $address
	 * @return string
	 */
	private function _create_address($address)
	{
		$strAddress = "";
		$iAddrCount = count($address); 
		for($i = 0; $i < $iAddrCount; $i++)
		{
			if (!empty($strAddress))
				$strAddress .= ", \r\n\t";
				
			if (trim($address[$i][1]) != "")
				$strAddress .= sprintf("\"%s\" <%s>", self::_mime_encode($address[$i][1]), $address[$i][0]);
			else
				$strAddress .= sprintf("%s", $address[$i][0]);
		}
		
		return $strAddress;
	}

	/**
	 * 获取邮件头信息
	 *
	 * @return string
	 */
	private function _get_header_info()
	{
		$headerInfo = array();
		$headerInfo["Date"] = sprintf("%s %s", date("D, j M Y G:i:s"), $this->timezone);
		$headerInfo["From"] = sprintf("\"%s\" <%s>", self::_mime_encode($this->fromname), trim($this->from));
		if (count($this->to) > 0)
			$headerInfo["To"] = self::_create_address($this->to);
		if (count($this->cc) > 0)
			$headerInfo["Cc"] = self::_create_address($this->cc);
		if (count($this->reply_to) > 0)
			$headerInfo["Reply-to"] = self::_create_address($this->reply_to);
		$headerInfo["Subject"] = self::_mime_encode(trim($this->subject));
		$headerInfo["X-Priority"] = $this->priority;
		$headerInfo["X-Mailer"] = $this->version;

		$headerInfo["Message-ID"] = md5(uniqid(rand())).strstr($this->from, '@');
		if ($this->request_notify)
		{
			$headerInfo["Disposition-Notification-To"] = sprintf("\"%s\" <%s>\r", self::_mime_encode($this->fromname), trim($this->from));
		}	
		
		return $headerInfo;
	}

	/**
	 * 创建邮件头信息
	 *
	 * @param boolean $bLite
	 * @return string
	 */
	private function _create_header($bLite = false)
	{
		$headerInfo = array();
		
		if (!$bLite)
		{
			$headerInfo[] = sprintf("Date: %s %s\r\n", date("D, j M Y G:i:s"), $this->timezone);
			$headerInfo[] = sprintf("From: \"%s\" <%s>\r\n", self::_mime_encode($this->fromname), trim($this->from));
	
			if (count($this->to) > 0)
				$headerInfo[] = sprintf("To: %s\r\n", self::_create_address($this->to));
			if (count($this->cc) > 0)
				$headerInfo[] = sprintf("Cc: %s\r\n", self::_create_address($this->cc));
			if (count($this->reply_to) > 0)
				$headerInfo[] = sprintf("Reply-To: %s\r\n", self::_create_address($this->reply_to));
	
			$headerInfo[] = sprintf("Subject: %s\r\n", self::_mime_encode(trim($this->subject)));
			$headerInfo[] = sprintf("X-Priority: %d\r\n", $this->priority);
			$headerInfo[] = sprintf("X-Mailer: %s\r\n", $this->version);
	
			$headerInfo[] = sprintf("Message-ID: <%s>\r\n", md5(uniqid(rand())).strstr($this->from, '@'));
		}
		
		$this->boundary = self::_get_boundary();
		if ($this->content_type == "html")
		{
			if (count($this->attachment) > 0)
			{
				$headerInfo[] = sprintf("Content-Type: multipart/mixed;\r\n");
				$headerInfo[] = sprintf("\tboundary=\"--=%s\"\r\n", $this->boundary);
			}
			else if (count($this->embed_file) > 0)
			{
				$headerInfo[] = sprintf("Content-Type: multipart/related; \r\n");
				$headerInfo[] = sprintf("\ttype=\"multipart/alternative\";\r\n");
				$headerInfo[] = sprintf("\tboundary=\"--=%s\"\r\n", $this->boundary);
			}
			else
			{
				$headerInfo[] = sprintf("Content-Type: multipart/alternative;\r\n");
				$headerInfo[] = sprintf("\tboundary=\"--=%s\"\r\n", $this->boundary);
			}
		}
		else
		{
			if (count($this->attachment) > 0)
			{
				$headerInfo[] = sprintf("Content-Type: multipart/mixed;\r\n");
				$headerInfo[] = sprintf("\tboundary=\"--=%s\"\r\n", $this->boundary);
			}
			else
			{
				$headerInfo[] = sprintf("Content-Type: text/plain; \r\n");
				$headerInfo[] = sprintf("\tcharset=\"%s\";\r\n", $this->charset);
				$headerInfo[] = sprintf("Content-Transfer-Encoding: %s\r\n", $this->encoding);
			}
		}
		
		if (!$bLite)
		{
			$headerInfo[] = "MIME-Version: 1.0\r\n";
			if ($this->request_notify)
			{
				$headerInfo[] = sprintf("Disposition-Notification-To: \"%s\" <%s>\r\n", self::_mime_encode($this->fromname), trim($this->from));
			}	
		}
		return join("", $headerInfo)."\r\n";
	}

	/**
	 * 创建邮件内容主体
	 *
	 * @return string
	 */
	private function _create_body()
	{
		$body = $this->body;
		$boundary = $this->boundary;
		$iAttachCount = count($this->attachment); 
		$iEmbedCount = count($this->embed_file);

		$mimetag = "";
		$msgbodytag = "";
		$msgbody = "";
		$embed_filebodytag = "";
		$embed_filebody = "";
		$attachbody = "";
		
		if ($this->content_type == 'html')
		{
			$mimetag = "This is a multi-part message in MIME format.\r\n\r\n";
			
			if ($iAttachCount > 0)
			{
				$attachbody = self::_create_attach_body($boundary);
			}
			 
			if ($iEmbedCount > 0)
			{
				if (!empty($attachbody))
				{
					$newboundary = self::_get_boundary();

					$embed_filebodytag .= sprintf("----=%s\r\n", $boundary);
					$embed_filebodytag .= sprintf("Content-Type: multipart/related;\r\n");
					$embed_filebodytag .= sprintf("\ttype=\"multipart/alternative\";\r\n");
					$embed_filebodytag .= sprintf("\tboundary=\"--=%s\"\r\n\r\n", $newboundary);
					
					$boundary = $newboundary;
				}
				
				$body = self::_adjust_embed_path($body);
				$embed_filebody = self::_create_embed_file_body($boundary);
			}
			
			if (!empty($attachbody) || !empty($embed_filebody))
			{
				$newboundary = self::_get_boundary();
				$msgbodytag .= sprintf("----=%s\r\n", $boundary);
				$msgbodytag .= sprintf("Content-Type: multipart/alternative;\r\n");
				$msgbodytag .= sprintf("\tboundary=\"--=%s\"\r\n\r\n", $newboundary);
				$boundary = $newboundary;
			}
			
			$msgbody .= self::_create_html_body($boundary, $body);
		}
		else
		{
			if ($iAttachCount > 0)
			{
				$mimetag = "This is a multi-part message in MIME format.\r\n\r\n";
				$attachbody = self::_create_attach_body($boundary);
			}
			else
			{
				$boundary = "";
			}
			$msgbody = self::_create_plain_body($boundary, $body);
		}

		$body = $mimetag;
		$body .= $embed_filebodytag;
		$body .= $msgbodytag;
		$body .= $msgbody;
		$body .= $embed_filebody;
		$body .= $attachbody;
		return trim($body)."\r\n";		
	}

	/**
	 * 加密码邮件主体
	 *
	 * @param string $body
	 * @return string
	 */
	private function _encode_body($body)
	{
		if ($this->encoding == 'base64')
		{
			$mime = chunk_split(base64_encode($body));
		}
		else
		{
			$mime = wordwrap($body, 76, "\r\n");
		}
		
		return trim($mime);
	}

	/**
	 * 创建文本内容
	 *
	 * @param string $boundary
	 * @param string $body
	 * @return string
	 */
	private function _create_plain_body($boundary = "", $body)
	{
		$encodebody = self::_encode_body($body);
		if (!empty($boundary)){
			$mime .= sprintf("----=%s\r\n", $boundary);
			$mime .= sprintf("Content-Type: text/plain;\r\n");
			$mime .= sprintf("\tcharset=\"%s\";\r\n", $this->charset);
			$mime .= sprintf("Content-Transfer-Encoding: %s\r\n\r\n", $this->encoding);
		}
		$mime .= sprintf("%s\r\n\r\n", $encodebody);
		return $mime;
	}

	/**
	 * 创建HTML内容
	 *
	 * @param string $boundary
	 * @param string $body
	 * @return string
	 */
	private function _create_html_body($boundary, $body)
	{
		$encodebody = self::_encode_body(strip_tags($body));
		$mime  = sprintf("----=%s\r\n", $boundary);
		$mime .= sprintf("Content-Type: text/plain;\r\n");
		$mime .= sprintf("\tcharset=\"%s\";\r\n", $this->charset);
		$mime .= sprintf("Content-Transfer-Encoding: %s\r\n\r\n", $this->encoding);
		$mime .= sprintf("%s\r\n\r\n", $encodebody);
		
		$encodebody = self::_encode_body($body);
		$mime .= sprintf("----=%s\r\n", $boundary);
		$mime .= sprintf("Content-Type: text/html;\r\n");
		$mime .= sprintf("\tcharset=\"%s\";\r\n", $this->charset);
		$mime .= sprintf("Content-Transfer-Encoding: %s\r\n\r\n", $this->encoding);
		$mime .= sprintf("%s\r\n\r\n", $encodebody);
		
		$mime .= sprintf("----=%s--\r\n\r\n", $boundary);
		return $mime;
	}

	private function _create_attach_body($boundary) 
	{
		$iAttachCount = count($this->attachment); 

		for($i = 0; $i < $iAttachCount; $i++)
		{
			$path = $this->attachment[$i][0];
			$filename = $this->attachment[$i][1];
			$name = $this->attachment[$i][2];
			$type = $this->attachment[$i][3];
			
			if (file_exists($path))
			{
				$mime .= sprintf("----=%s\r\n", $boundary);
				$mime .= sprintf("Content-Type: %s; name=\"%s\"\r\n", $type, self::_mime_encode($name));
				$mime .= "Content-Transfer-Encoding: base64\r\n";
				$mime .= sprintf("Content-Disposition: attachment; filename=\"%s\"\r\n\r\n", self::_mime_encode($name));
				$mime .= sprintf("%s\r\n\r\n", self::_encode_file($path));
			}
		}
		$mime .= sprintf("----=%s--\r\n\r\n", $boundary);
		return $mime;
	}

	private function _create_embed_file_body($boundary)
	{
		$iEmbedCount = count($this->embed_file); 
		for($i = 0; $i < $iEmbedCount; $i++)
		{
			$path = $this->embed_file[$i][0];
			$filename = $this->embed_file[$i][1];
			$name = $this->embed_file[$i][2];
			$type = $this->embed_file[$i][3];
			$cid = $this->embed_file[$i][4];
			
			if (file_exists($path))
			{
				$mime .= sprintf("----=%s\r\n", $boundary);
				$mime .= sprintf("Content-Type: %s; name=\"%s\"\r\n", $type, self::_mime_encode($name));
				$mime .= "Content-Transfer-Encoding: base64\r\n";
				$mime .= sprintf("Content-ID: <%s>\r\n", $cid);
				$mime .= sprintf("Content-Disposition: inline; filename=\"%s\"\r\n\r\n", self::_mime_encode($name));
				$mime .= sprintf("%s\r\n\r\n", self::_encode_file($path));
			}
		}

		$mime .= sprintf("----=%s--\r\n\r\n", $boundary);

		return $mime;
	}
		
	private function _send_mail($msgdata)
	{
		$smtp = new SMTP;
		$smtp->debug = $this->debug;
		if (!$smtp->connect($this->host, $this->port, $this->timeout))
		{
			$this->error_msg = "SMTP Error: could not connect to SMTP host server";
			$this->error_msg .= "[".$this->host.":".$this->port."]";
			return false;
		}

		if ($this->auth_login)
		{
			if (!$smtp->auth_hello($this->helo, $this->auth_user, $this->auth_pass))
			{
				$this->error_msg = "SMTP Error: Invalid username/password";
				if ($smtp->error_msg)
					$this->error_msg .= "<br>".$smtp->error_msg;
					
				return false;
			}
		} 
		else
		{
			$smtp->hello($this->helo);
		}
		
		if (!$smtp->mail_from(sprintf("<%s>", $this->from)))
		{
			$this->error_msg = "SMTP Error: Mail from [".$this->from."] not accepted.";
			if ($smtp->error_msg)
				$this->error_msg .= "<br>".$smtp->error_msg;
			return false;
		}
		
		$iToCount = count($this->to); 
		for($i = 0; $i < $iToCount; $i++)
		{
			if (!$smtp->recipient(sprintf("<%s>", $this->to[$i][0])))
			{
				$this->error_msg = "SMTP Error: recipient [".$this->to[$i][0]."] not accepted.";
				if ($smtp->error_msg)
					$this->error_msg .= "<br>".$smtp->error_msg;
				return false;
			}
		}
			
		$iCcCount = count($this->cc); 
		for($i = 0; $i < $iCcCount; $i++)
		{
			if (!$smtp->recipient(sprintf("<%s>", $this->cc[$i][0])))
			{
				$this->error_msg = "SMTP Error: recipient [".$this->cc[$i][0]."] not accepted.";
				if ($smtp->error_msg)
					$this->error_msg .= "<br>".$smtp->error_msg;
				return false;
			}
		}

		$iBccCount = count($this->bcc); 
		for($i = 0; $i < $iBccCount; $i++)
		{
			if (!$smtp->recipient(sprintf("<%s>", $this->bcc[$i][0])))
			{
				$this->error_msg = "SMTP Error: recipient [".$this->bcc[$i][0]."] not accepted.";
				if ($smtp->error_msg)
					$this->error_msg .= "<br>".$smtp->error_msg;
				return false;
			}
		}

		if (!$smtp->data($msgdata))
		{
			$this->error_msg = "SMTP Error: data not accepted";
			if ($smtp->error_msg)
			{
				$this->error_msg .= "<br>".$smtp->error_msg;
			}
			return false;
		}
		$smtp->_quit();
	}
}

class SMTP
{
	public $port = 25; 		
	public $debug;          	
	public $error_msg;       	

	public $smtp_obj;      	
	public $CRLF = "\r\n";  	

	public function __construct()
	{
		$this->smtp_obj = 0;
		$this->error_msg = "";
		$this->debug = 0;
	}

	public function __destruct() //析构函数
	{
	}

	/**
	 * 连接邮件服务器
	 *
	 * @param string $host 主机
	 * @param integer $port 端口
	 * @param integer $tval 超时秒
	 * @return boolean
	 */
	public function connect($host, $port = 25, $tval = 30)
	{
		$this->error_msg = "";
		if (self::_connected())
		{
			$this->error_msg = "Already connected to a server";
			return false;
		}
		$this->smtp_obj = @fsockopen($host, $port, $errno, $errstr, $tval);   
		if (empty($this->smtp_obj))
		{
			$this->error_msg = "Failed to connect to server ($errno $errstr)";
			return false;
		}
		$announce = self::_get_lines();
		return true;
	}

	private function _close()
	{
		$this->error_msg = ""; 
		if (!empty($this->smtp_obj))
		{ 
			fclose($this->smtp_obj);
			$this->smtp_obj = 0;
		}
	}

	public function hello($host = "")
	{
		$this->error_msg = "";
		if (!self::_connected())
		{
			$this->error_msg = "Called hello() without being connected";
			return false;
		}
		
		if (empty($host)){$host = "SMTP Client";}
		self::_send_line("HELO ".$host);
		$rply = self::_get_lines();
		$code = substr($rply,0,3);

		if ($code != 250)
		{
			$this->error_msg = $rply;
			return false;
		}
		return true;
	}

	public function auth_hello($host = "", $user = "", $pass = "") 
	{

		$this->error_msg = null; 
		if (!self::_connected())
		{
			$this->error_msg = "Called hello() without being connected";
			return false;
		}

		if (empty($host)){$host = "SMTP Client";}

		self::_send_line("EHLO ".$host);

		$rply = self::_get_lines();
		$code = substr($rply, 0, 3);
		if ($code != 250)
		{
			$this->error_msg = $rply;
			return false;
		}
		
		self::_send_line("AUTH LOGIN");
		$rply = self::_get_lines();
		$code = substr($rply,0,3);

		if ($code != 334)
		{
			$this->error_msg = $rply;
			return false;
		}

		self::_send_line(base64_encode($user));
		$rply = self::_get_lines();
		$code = substr($rply, 0, 3);

		if ($code != 334)
		{
			$this->error_msg = $rply;
			return false;
		}

		self::_send_line(base64_encode($pass));
		$rply = self::_get_lines();
		$code = substr($rply, 0, 3);
		if ($code != 235)
		{
			$this->error_msg = $rply;
			return false;
		}
		
		return true;
	}

	/**
	 * 邮件来源
	 *
	 * @param string $from
	 * @return boolean
	 */
	public function mail_from($from)
	{
		$this->error_msg = null; 

		if (!self::_connected())
		{
			$this->error_msg = "Called Mail() without being connected";
			return false;
		}
		self::_send_line("MAIL FROM:".$from);
		$rply = self::_get_lines();
		$code = substr($rply,0,3);

		if ($code != 250)
		{
			$this->error_msg = $rply;
			return false;
		}
		return true;
	}

	public function recipient($to) 
	{
		$this->error_msg = null; 
		if (!self::_connected())
		{
			$this->error_msg = "Called recipient() without being connected";
			return false;
		}
		self::_send_line("RCPT TO:".$to);
		$rply = self::_get_lines();
		$code = substr($rply,0,3);

		if ($code != 250 && $code != 251)
		{
			$this->error_msg = $rply;
			return false;
		}
		return true;
	}

	public function data($msg_data)
	{
		$this->error_msg = ""; 
		if (!self::_connected())
		{
			$this->error_msg = "Called data() without being connected";
			return false;
		}

		self::_send_line("DATA");
		$rply = self::_get_lines();
		$code = substr($rply, 0, 3);

		if ($code != 354)
		{
			$this->error_msg = $rply;
			return false;
		}

		self::_send_line($msg_data);
		self::_send_line(".");

		$rply = self::_get_lines();
		$code = substr($rply,0,3);

		if ($code != 250)
		{
			$this->error_msg = $rply;
			return false;
		}
		return true;
	}
	public function _quit($close_on_error = true)
	{
		$this->error_msg = null; 
		if (!self::_connected())
		{
			$this->error_msg = "Called _quit() without being connected";
			return false;
		}
		self::_send_line("QUIT");
		$byemsg = self::_get_lines();
		$rval = true;
		$e = null;
		$code = substr($byemsg,0,3);
		if ($code != 221)
		{
			$e = $byemsg;
			$this->error_msg = $byemsg;
			$rval = false;
		}

		if (empty($e) || $close_on_error)
		{
			self::_close();
		}
		return $rval;
	}
	private function _connected()
	{
		if (!empty($this->smtp_obj))
		{
			$sock_status = socket_get_status($this->smtp_obj);
			if ($sock_status["eof"])
			{
				self::_close();
				return false;
			}
			return true;
		} 
		return false;
	}
	private function _get_lines()
	{
		$data = "";
		
		while($str = fgets($this->smtp_obj, 512))
		{
			$data .= $str;
			if (substr($str, 3, 1) == " "){break;}
		}
		
		if ($this->debug)
		{
			$tmp = ereg_replace("(\r|\n)", "", $data);
			echo("<font style=\"font-size:12px; font-family: Courier New; background-color: white; color: black;\"><- <b>".htmlspecialchars($tmp)."</b></font><br>\r\n");
			flush();
		}
		return $data;
	}
	private function _send_line($data)
	{
		fputs($this->smtp_obj, $data.$this->CRLF);
		
		if ($this->debug)
		{
			$data = htmlspecialchars($data);
			echo("<font style=\"font-size:12px; font-family: Courier New; background-color: white; color: black;\">-> ".nl2br($data)."</font><br>\r\n");
			flush();
		}
	}
}
/*
$smtp = new EmailSmtp();
$smtp->ready("ssl://smtp.gmail.com", 465, "zhoupeng@uibiz.com", "zhoupeng10", "utf-8");
$smtp->is_html();
$smtp->add_to("zhoupeng10@gmail.com", "zhou sir");
$smtp->set_from("zhoupeng@uibiz.com", "apeng");
$smtp->subject = "just test";
$smtp->body =  "test test test test test test test test test test 周鹏 10 ~!@#$%&*() " ;//邮件内容
echo ($smtp->send()) ? "succeed" : "fail";
*/
?>